<?php
/**
 * In this file the class '\UF\Drawing\ColorTool' is defined.
 *
 * @category   UniKap-Framework
 * @package    Drawing
 * @subpackage Core
 * @author     Ulf -UniKado- Kadner <ulfikado@gmail.com>
 * @since      2014-04-04 16:17
 * @version    0.1
 */

namespace UF\Drawing
{

    /**
     * This class is a static helper class for web colors.
     *
     * @since  v0.1
     */
    class ColorTool
    {

        # <editor-fold defaultstate="collapsed" desc="- - - -   P R I V A T E   S T A T I C   F I E L D S   - - - - - - - - - - - - - -">

        # <editor-fold defaultstate="collapsed" desc="Color name => RGB Assocs">

        /**
         * Associates RGB color definitions (numeric array with 3 elements) to netscape web color names (keys).
         *
         * @var    array
         * @since  v0.1
         */
        private static $ColornameRGB = [
            'aliceblue'  => [ 240, 248, 255 ], 'antiquewhite'   => [ 250, 235, 215 ], 'aqua'       => [ 0,   255, 255 ],
            'aquamarine' => [ 127, 255, 212 ], 'azure'          => [ 240, 255, 255 ], 'beige'      => [ 245, 245, 220 ],
            'bisque'     => [ 255, 228, 196 ], 'black'          => [ 0,   0,   0   ], 'blue'       => [ 0,   0,   255 ],
            'blueviolet' => [ 138, 43,  226 ], 'blanchedalmond' => [ 255, 235, 205 ], 'brown'      => [ 165, 42,  42  ],
            'burlywood'  => [ 222, 184, 135 ], 'cadetblue'      => [ 95,  158, 160 ], 'chartreuse' => [ 127, 255, 0   ],
            'chocolate'  => [ 210, 105, 30  ], 'cornflowerblue' => [ 100, 149, 237 ], 'coral'      => [ 255, 127, 80  ],
            'cornsilk'   => [ 255, 248, 220 ], 'darkgoldenrod'  => [ 184, 134, 11  ], 'cyan'       => [ 0,   255, 255 ],
            'darkblue'   => [ 0,   0,   139 ], 'darkolivegreen' => [ 85,  107, 47  ], 'crimson'    => [ 220, 20,  60  ],
            'darkcyan'   => [ 0,   139, 139 ], 'darkslateblue'  => [ 72,  61,  139 ], 'darkgray'   => [ 169, 169, 169 ],
            'darkgreen'  => [ 0,   100, 0   ], 'darkmagenta'    => [ 139, 0,   139 ], 'darkkhaki'  => [ 189, 183, 107 ],
            'darkorange' => [ 255, 140, 0   ], 'darkseagreen'   => [ 143, 188, 143 ], 'darkorchid' => [ 153, 50,  204 ],
            'darksalmon' => [ 233, 150, 122 ], 'darkslategray'  => [ 47,  79,  79  ], 'darkred'    => [ 139, 0,   0   ],
            'darkviolet' => [ 148, 0,   211 ], 'darkturquoise'  => [ 0,   206, 209 ], 'deeppink'   => [ 255, 20,  147 ],
            'dodgerblue' => [ 30,  144, 255 ], 'deepskyblue'    => [ 0,   191, 255 ], 'dimgray'    => [ 105, 105, 105 ],
            'firebrick'  => [ 178, 34,  34  ], 'floralwhite'    => [ 255, 250, 240 ], 'fuchsia'    => [ 255, 0,   255 ],
            'gainsboro'  => [ 220, 220, 220 ], 'forestgreen'    => [ 34,  139, 34  ], 'ghostwhite' => [ 248, 248, 255 ],
            'goldenrod'  => [ 218, 165, 32  ], 'lavenderblush'  => [ 255, 240, 245 ], 'gold'       => [ 255, 215, 0   ],
            'indianred'  => [ 205, 92,  92  ], 'lightgoldenrodyellow'=>[250,250,210], 'gray'       => [ 128, 128, 128 ],
            'lightblue'  => [ 173, 216, 230 ], 'lemonchiffon'   => [ 255, 250, 205 ], 'green'      => [ 0,   128, 0   ],
            'honeydew'   => [ 240, 255, 240 ], 'greenyellow'    => [ 173, 255, 47  ], 'hotpink'    => [ 255, 105, 180 ],
            'lightcoral' => [ 240, 128, 128 ], 'lightseagreen'  => [ 32,  178, 170 ], 'indigo'     => [ 75,  0,   130 ],
            'lightgreen' => [ 144, 238, 144 ], 'lightsalmon'    => [ 255, 160, 122 ], 'ivory'      => [ 255, 255, 240 ],
            'lawngreen'  => [ 124, 252, 0   ], 'lightskyblue'   => [ 135, 206, 250 ], 'khaki'      => [ 240, 230, 140 ],
            'lightcyan'  => [ 224, 255, 255 ], 'lightslategray' => [ 119, 136, 153 ], 'lavender'   => [ 230, 230, 250 ],
            'lightgrey'  => [ 211, 211, 211 ], 'lightsteelblue' => [ 176, 196, 222 ], 'lime'       => [ 0,   255, 0   ],
            'lightpink'  => [ 255, 182, 193 ], 'mediumaquamarine' => [102,205, 170 ], 'maroon'     => [ 128, 0,   0   ],
            'limegreen'  => [ 50,  205, 50  ], 'lightyellow'    => [ 255, 255, 224 ], 'linen'      => [ 250, 240, 230 ],
            'mediumblue' => [ 0,   0,   205 ], 'mediumorchid'   => [ 186, 85,  211 ], 'magenta'    => [ 255, 0,   255 ],
            'mintcream'  => [ 245, 255, 250 ], 'mediumpurple'   => [ 147, 112, 216 ], 'navy'       => [ 0,   0,   128 ],
            'mistyrose'  => [ 255, 228, 225 ], 'mediumseagreen' => [ 60,  179, 113 ], 'moccasin'   => [ 255, 228, 181 ],
            'olivedrab'  => [ 107, 142, 35  ], 'mediumslateblue'=> [ 123, 104, 238 ], 'olive'      => [ 128, 128, 0   ],
            'orangered'  => [ 255, 69,  0   ], 'mediumspringgreen' => [0, 250, 154 ], 'oldlace'    => [ 253, 245, 230 ],
            'palegreen'  => [ 152, 251, 152 ], 'mediumturquoise'=> [ 72,  209, 204 ], 'orange'     => [ 255, 165, 0   ],
            'navajowhite'=> [ 255, 222, 173 ], 'mediumvioletred'=> [ 199, 21,  133 ], 'orchid'     => [ 218, 112, 214 ],
            'papayawhip' => [ 255, 239, 213 ], 'midnightblue'   => [ 25,  25,  112 ], 'peru'       => [ 205, 133, 63  ],
            'peachpuff'  => [ 255, 218, 185 ], 'palegoldenrod'  => [ 238, 232, 170 ], 'pink'       => [ 255, 192, 203 ],
            'powderblue' => [ 176, 224, 230 ], 'paleturquoise ' => [ 175, 238, 238 ], 'plum'       => [ 221, 160, 221 ],
            'rosybrown'  => [ 188, 143, 143 ], 'palevioletred'  => [ 216, 112, 147 ], 'purple'     => [ 128, 0,   128 ],
            'royalblue'  => [ 65,  105, 225 ], 'saddlebrown'    => [ 139, 69,  19  ], 'red'        => [ 255, 0,   0   ],
            'sandybrown' => [ 244, 164, 96  ], 'springgreen'    => [ 0,   255, 127 ], 'seagreen'   => [ 46,  139, 87  ],
            'salmon'     => [ 250, 128, 114 ], 'seashell'       => [ 255, 245, 238 ], 'sienna'     => [ 160, 82,  45  ],
            'silver'     => [ 192, 192, 192 ], 'skyblue'        => [ 135, 206, 235 ], 'slateblue'  => [ 106, 90,  205 ],
            'slategray'  => [ 112, 128, 144 ], 'snow'           => [ 255, 250, 250 ], 'steelblue'  => [ 70,  130, 180 ],
            'tan'        => [ 210, 180, 140 ], 'teal'           => [ 0,   128, 128 ], 'thistle'    => [ 216, 191, 216 ],
            'tomato'     => [ 255, 99,  71  ], 'turquoise'      => [ 64,  224, 208 ], 'violet'     => [ 238, 130, 238 ],
            'whitesmoke' => [ 245, 245, 245 ], 'wheat'          => [ 245, 222, 179 ], 'white'      => [ 255, 255, 255 ],
            'yellow'     => [ 255, 255, 0   ], 'yellowgreen'    => [ 154, 205, 50]
        ];

        # </editor-fold>

        # <editor-fold defaultstate="collapsed" desc="Colors name => HEX Assocs">

        /**
         * Associates HEX color definitions (#RRGGBB) to netscape web color names (keys).
         *
         * @var    array
         * @since  v0.1
         */
        private static $ColornameHex = [
            'aliceblue'            => '#F0F8FF',  'antiquewhite'         => '#FAEBD7',  'aqua'             => '#00FFFF',
            'aquamarine'           => '#7FFFD4',  'azure'                => '#F0FFFF',  'beige'            => '#F5F5DC',
            'bisque'               => '#FFE4C4',  'blanchedalmond'       => '#FFEBCD',  'black'            => '#000000',
            'blueviolet'           => '#8A2BE2',  'burlywood'            => '#DEB887',  'blue'             => '#0000FF',
            'cadetblue'            => '#5F9EA0',  'chartreuse'           => '#7FFF00',  'brown'            => '#A52A2A',
            'chocolate'            => '#D2691E',  'coral'                => '#FF7F50',  'cornflowerblue'   => '#6495ED',
            'cornsilk'             => '#FFF8DC',  'crimson'              => '#DC143C',  'cyan'             => '#00FFFF',
            'darkblue'             => '#00008B',  'darkcyan'             => '#008B8B',  'darkgoldenrod'    => '#B8860B',
            'darkgray'             => '#A9A9A9',  'darkgreen'            => '#006400',  'darkkhaki'        => '#BDB76B',
            'darkmagenta'          => '#8B008B',  'darkolivegreen'       => '#556B2F',  'darkorange'       => '#FF8C00',
            'darkorchid'           => '#9932CC',  'darkred'              => '#8B0000',  'darksalmon'       => '#E9967A',
            'darkseagreen'         => '#8FBC8F',  'darkslateblue'        => '#483D8B',  'darkslategray'    => '#2F4F4F',
            'darkturquoise'        => '#00CED1',  'darkviolet'           => '#9400D3',  'deeppink'         => '#FF1493',
            'deepskyblue'          => '#00BFFF',  'dimgray'              => '#696969',  'dodgerblue'       => '#1E90FF',
            'firebrick'            => '#B22222',  'floralwhite'          => '#FFFAF0',  'forestgreen'      => '#228B22',
            'fuchsia'              => '#FF00FF',  'gainsboro'            => '#DCDCDC',  'ghostwhite'       => '#F8F8FF',
            'gold'                 => '#FFD700',  'goldenrod'            => '#DAA520',  'gray'             => '#808080',
            'green'                => '#008000',  'greenyellow'          => '#ADFF2F',  'honeydew'         => '#F0FFF0',
            'hotpink'              => '#FF69B4',  'indianred'            => '#CD5C5C',  'indigo'           => '#4B0082',
            'ivory'                => '#FFFFF0',  'khaki'                => '#F0E68C',  'lavender'         => '#E6E6FA',
            'lavenderblush'        => '#FFF0F5',  'lawngreen'            => '#7CFC00',  'lemonchiffon'     => '#FFFACD',
            'lightblue'            => '#ADD8E6',  'lightcoral'           => '#F08080',  'lightcyan'        => '#E0FFFF',
            'lightgoldenrodyellow' => '#FAFAD2',  'lightgrey'            => '#D3D3D3',  'lightgreen'       => '#90EE90',
            'lightpink'            => '#FFB6C1',  'lightsalmon'          => '#FFA07A',  'lightseagreen'    => '#20B2AA',
            'lightskyblue'         => '#87CEFA',  'lightslategray'       => '#778899',  'lightsteelblue'   => '#B0C4DE',
            'lightyellow'          => '#FFFFE0',  'lime'                 => '#00FF00',  'limegreen'        => '#32CD32',
            'linen'                => '#FAF0E6',  'magenta'              => '#FF00FF',  'maroon'           => '#800000',
            'mediumaquamarine'     => '#66CDAA',  'mediumblue'           => '#0000CD',  'mediumorchid'     => '#BA55D3',
            'mediumpurple'         => '#9370D8',  'mediumseagreen'       => '#3CB371',  'mediumslateblue'  => '#7B68EE',
            'mediumspringgreen'    => '#00FA9A',  'mediumturquoise'      => '#48D1CC',  'mediumvioletred'  => '#C71585',
            'midnightblue'         => '#191970',  'mintcream'            => '#F5FFFA',  'mistyrose'        => '#FFE4E1',
            'moccasin'             => '#FFE4B5',  'navajowhite'          => '#FFDEAD',  'navy'             => '#000080',
            'oldlace'              => '#FDF5E6',  'olive'                => '#808000',  'olivedrab'        => '#6B8E23',
            'orange'               => '#FFA500',  'orangered'            => '#FF4500',  'orchid'           => '#DA70D6',
            'palegoldenrod'        => '#EEE8AA',  'palegreen'            => '#98FB98',  'paleturquoise'    => '#AFEEEE',
            'palevioletred'        => '#D87093',  'papayawhip'           => '#FFEFD5',  'peachpuff'        => '#FFDAB9',
            'peru'                 => '#CD853F',  'pink'                 => '#FFC0CB',  'plum'             => '#DDA0DD',
            'powderblue'           => '#B0E0E6',  'purple'               => '#800080',  'red'              => '#FF0000',
            'rosybrown'            => '#BC8F8F',  'royalblue'            => '#4169E1',  'saddlebrown'      => '#8B4513',
            'salmon'               => '#FA8072',  'sandybrown'           => '#F4A460',  'seagreen'         => '#2E8B57',
            'seashell'             => '#FFF5EE',  'sienna'               => '#A0522D',  'silver'           => '#C0C0C0',
            'skyblue'              => '#87CEEB',  'slateblue'            => '#6A5ACD',  'slategray'        => '#708090',
            'snow'                 => '#FFFAFA',  'springgreen'          => '#00FF7F',  'steelblue'        => '#4682B4',
            'tan'                  => '#D2B48C',  'teal'                 => '#008080',  'thistle'          => '#D8BFD8',
            'tomato'               => '#FF6347',  'turquoise'            => '#40E0D0',  'violet'           => '#EE82EE',
            'wheat'                => '#F5DEB3',  'white'                => '#FFFFFF',  'whitesmoke'       => '#F5F5F5',
            'yellow'               => '#FFFF00',  'yellowgreen'          => '#9ACD32'
        ];

        # </editor-fold>

        # </editor-fold>

        # <editor-fold defaultstate="collapsed" desc="- - - >   H I D D E N   C O N S T R U C T O R   - - - - - - - - - - - - - - - - -">

        /**
         * Hidden because class usage is only static.
         *
         * @since  v0.1
         */
        private function __construct() {  }

        # </editor-fold>

        # <editor-fold defaultstate="collapsed" desc="- - - -   P U B L I C   S T A T I C   M E T H O D S   - - - - - - - - - - - - - -">

        /**
         * Gives back, whether the defined color value is a hexadecimal notation.
         *
         * @param  string $colorDefinition
         * @return bool
         * @since  v0.1
         */
        public static function IsHexFormat( $colorDefinition )
        {
            if ( \is_array( $colorDefinition ) ) return false;
            return (bool) \preg_match( '~^#?([a-f0-9]{3}|[a-f0-9]{6}|[a-f0-9]{8})$~i', $colorDefinition );
        }

        /**
         * Converts the indicated color into a RGB color definition. This is is defined as an array numerically
         * indexed with 3 elements.
         *
         * @param  string $colorDefinition THe color definition
         * @return array Or boolean FALSE
         * @since  v0.1
         */
        public static function Color2Rgb( $colorDefinition )
        {
            if ( \is_array( $colorDefinition ) )
            {
                if ( 2 < \count( $colorDefinition ) && 5 > \count( $colorDefinition ) ) return $colorDefinition;
                return false;
            }
            if ( self::IsHexFormat( $colorDefinition ) ) return self::Hex2Rgb( $colorDefinition );
            $uc = \strtolower( $colorDefinition );
            if ( isset( self::$ColornameRGB[$uc] ) ) return self::$ColornameRGB[$uc];
            if ( false !== ( $hex = self::Rgb2Hex( $colorDefinition ) ) ) return self::Hex2Rgb( $hex );
            return false;
        }

        /**
         * Converts the defined color to the Hexadecimal format #RRGGBB.
         *
         * @param  string|array $colorDefinition The color definition to convert
         * @return string Or boolean FALSE
         * @since  v0.1
         */
        public static function Color2Hex( $colorDefinition )
        {
            if ( \is_array( $colorDefinition ) )
            {
                if ( \count( $colorDefinition ) != 3 ) return false;
                return self::Rgb2Hex( $colorDefinition );
            }
            if ( self::IsHexFormat( $colorDefinition ) ) return $colorDefinition;
            $uc = \strtolower( $colorDefinition );
            if ( isset( self::$ColornameHex[$uc] ) ) return \strtolower( self::$ColornameHex[$uc] );
            if ( false !== ( $hex = self::Rgb2Hex( $colorDefinition ) ) ) return $hex;
            return false;
        }

        /**
         * Converts a hexadecimal color definition into a RGB color definition (numeric array with 3 elements)
         *
         * @param  string $color
         * @return array Or boolean FALSE.
         * @since  v0.1
         */
        public static function Hex2Rgb( $color )
        {
            if ( $color[0] == '#' )       $color = \substr( $color, 1 );
            if ( \strlen( $color ) == 8 ) $color = \substr( $color, 2 );
            if ( \strlen( $color ) == 6 )
                list($r, $g, $b) = array( $color[0] . $color[1], $color[2] . $color[3], $color[4] . $color[5] );
            elseif ( \strlen( $color ) == 3 )
                list($r, $g, $b) = array( $color[0] . $color[0], $color[1] . $color[1], $color[2] . $color[2] );
            else return false;
            return array( \hexdec( $r ), \hexdec( $g ), \hexdec( $b ) );
        }

        /**
         * Converts a RGB color definition in a Hexadecimal color representation.
         *
         * If you will convert a RGB color array or a RGB color string use it in first parameter and left the other
         * 2 parameters black.
         *
         *
         * @param  array|string|integer $r Red value or RGB array or RGB string
         * @param  integer $g The Green value.
         * @param  integer $b The blue value.
         * @return string Or boolean FALSE
         * @since  v0.1
         */
        public static function Rgb2Hex( $r, $g=-1, $b=-1 )
        {
            $m = null;
            if ( \is_array( $r ) )
            {
                if ( \count( $r ) != 3 ) return false;
                list( $r, $g, $b ) = $r;
            }
            elseif ( \preg_match( '~^(rgb\s*\()?(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)?$~', $r, $m ) )
            {
                list( $ignore, $r, $g, $b ) = $m;
            }
            elseif ( !\is_int( $r ) ) { return false; }
            $ignore = null;
            $r1 = \intval( $r ); $g1 = \intval( $g ); $b1 = \intval( $b );
            $r = \dechex( $r1 < 0 ? 0 : ( $r1 > 255 ? 255 : $r1 ) );
            $g = \dechex( $g1 < 0 ? 0 : ( $g1 > 255 ? 255 : $g1 ) );
            $b = \dechex( $b1 < 0 ? 0 : ( $b1 > 255 ? 255 : $b1 ) );
            return \sprintf( '#%02s%02s%02s', $r, $g, $b );
        }

        /**
         * Investigates whether the submitted color definition corresponds to a color with a known color name.
         * If so, then the methode returns TRUE and the color name is returned in $colornameResult.
         *
         * @param  string|array $colorDefinition The color definition
         * @param  string $colornameResult Contains the Result, if Method returns TRUE.
         * @return boolean
         * @since  v0.1
         */
        public static function IsNamedColor( $colorDefinition )
        {
            if ( false === ( $hex = self::Color2Hex( $colorDefinition ) ) ) return false;
            return \in_array( \strtoupper( $hex ), self::$ColornameHex );
        }

        # </editor-fold>

    }

}

